package com.orifine.sql.chain;

import com.orifine.orm.model.ColumnModel;
import com.orifine.sql.SyntaxString;

public class ChainRestriction implements ChainRestrictionsElement {
	private ChainRestrictionType type;
	private String value1;
	private String value2;
	private String value3;
	private String[] values;

	private ChainRestriction(ChainRestrictionType type, ColumnModel column1, ColumnModel column2) {
		this.type = type;
		this.value1 = column1.getTable().getName() + "." + column1.getName();
		this.value2 = column2.getTable().getName() + "." + column2.getName();
	}

	private ChainRestriction(ChainRestrictionType type, ColumnModel column1, Object value) {
		this.type = type;
		this.value1 = column1.getTable().getName() + "." + column1.getName();
		this.value2 = value.toString();
	}

	private ChainRestriction(ChainRestrictionType type, ColumnModel column, Object value1, Object value2) {
		this.type = type;
		this.value1 = column.getTable().getName() + "." + column.getName();
		this.value2 = value1.toString();
		this.value3 = value2.toString();
	}

	private ChainRestriction(ChainRestrictionType type, ColumnModel column, Object[] values) {
		this.type = type;
		this.value1 = column.getTable().getName() + "." + column.getName();
		this.values = new String[values.length];
		for (int i = 0; i < values.length; i++) {
			this.values[i] = values[i].toString();
		}
	}

	private ChainRestriction(ChainRestrictionType type, ColumnModel column) {
		this.type = type;
		this.value1 = column.getTable().getName() + "." + column.getName();
	}
	
	@Override
	public void chain(SyntaxString out) {
		switch(type){
		case GT:
			out.addWord(value1).append(">").append(value2);
			break;
		case LT:
			out.addWord(value1).append("<").append(value2);
			break;
		case EQ:
			out.addWord(value1).append("=").append(value2);
			break;
		case GE:
			out.addWord(value1).append(">=").append(value2);
			break;
		case LE:
			out.addWord(value1).append("<=").append(value2);
			break;
		case UEQ:
			out.addWord(value1).append("<>").append(value2);
			break;
		case BETWEEN_AND:
			out.addWord(value1).addWord("BETWEEN").addWord(value2).addWord("AND").addWord(value3);
			break;
		case IN:
			out.addWord(value1).addWord("IN").append("(");
			boolean isFirst = true;
			for(String value : values){
				if(isFirst){
					isFirst = false;
				} else {
					out.append(",");
				}
				out.addWord(value);
			}
			out.append(")");
			break;
		case LIKE:
			out.addWord(value1).addWord("LIKE").addWord(value2);
			break;
		case IS_NULL:
			out.addWord(value1).addWord("IS NULL");
			break;
		case IS_NOT_NULL:
			out.addWord(value1).addWord("IS NOT NULL");
			break;
		}
	}

	@Override
	public String sql() {
		SyntaxString out = new SyntaxString();
		chain(out);
		return out.toString();
	}

	/**
	 * 大于
	 */
	public static ChainRestriction gt(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.GT, column1, column2);
	}

	public static ChainRestriction gt(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.GT, column1, value);
	}

	/**
	 * 小于
	 */
	public static ChainRestriction lt(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.LT, column1, column2);
	}

	public static ChainRestriction lt(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.LT, column1, value);
	}

	/**
	 * 等于
	 */
	public static ChainRestriction eq(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.EQ, column1, column2);
	}

	public static ChainRestriction eq(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.EQ, column1, value);
	}

	/**
	 * 大于或等于
	 */
	public static ChainRestriction ge(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.GE, column1, column2);
	}

	public static ChainRestriction ge(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.GE, column1, value);
	}

	/**
	 * 小于或等于
	 */
	public static ChainRestriction le(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.LE, column1, column2);
	}

	public static ChainRestriction le(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.LE, column1, value);
	}

	/**
	 * 不等于
	 */
	public static ChainRestriction ueq(ColumnModel column1, ColumnModel column2) {
		return new ChainRestriction(ChainRestrictionType.UEQ, column1, column2);
	}

	public static ChainRestriction ueq(ColumnModel column1, Object value) {
		return new ChainRestriction(ChainRestrictionType.UEQ, column1, value);
	}

	public static ChainRestriction betweenAnd(ColumnModel column, Object value1, Object value2) {
		return new ChainRestriction(ChainRestrictionType.BETWEEN_AND, column, value1, value2);
	}

	public static ChainRestriction link(ColumnModel column, Object value) {
		return new ChainRestriction(ChainRestrictionType.LIKE, column, value);
	}

	public static ChainRestriction in(ColumnModel column, Object[] values) {
		return new ChainRestriction(ChainRestrictionType.IN, column, values);
	}

	public static ChainRestriction isNull(ColumnModel column) {
		return new ChainRestriction(ChainRestrictionType.IS_NULL, column);
	}

	public static ChainRestriction isNotNull(ColumnModel column) {
		return new ChainRestriction(ChainRestrictionType.IS_NOT_NULL, column);
	}
}
